/**
 * 
 */
package start;

import io.BlastClustReader;
import io.FastaReader;
import io.ISequenceReader;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;
import java.util.TreeSet;

import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;

import visualization.singleview.SingleSequenceView;
import dataTypes.Cluster;
import dataTypes.PyroData;

/**
 * @author Christian
 * 
 */

public class MainWindow extends JFrame implements ActionListener {
	private static final long serialVersionUID = 260775956387913884L;

	private static final int GENESINMENU = 10;

	JMenuBar mainMenu;

	JMenu fileMenu;
	JMenuItem loadMenuItem;

	JMenu singleSeqMenu;
	JMenuItem[] sequenceMenuItem;
	JMenuItem singleSeqSearchMI;
	JMenuItem singleSeqNextMI;
	JMenuItem singleSeqPrevMI;
	int seqCurrentFirst = 0;

	JMenu helpMenu;
	JMenuItem aboutMenuItem;
	JMenuItem helpMenuItem;

	JMenu multipleSeqMenu;
	JMenuItem msClusterMI[];
	JMenuItem msLoadClusterMI;
	JMenuItem msRandomMI;

	JDesktopPane desktop;

	ISequenceReader pyroDataIn;

	Map<String, PyroData> sequenceData = new TreeMap<String, PyroData>();

	TreeSet<String> sequenceName = new TreeSet<String>();

	TreeMap<String, Cluster> clusterMap;

	public MainWindow(String name) {
		super(name);
		init();
	}

	public void init() {

		desktop = new JDesktopPane();
		this.setContentPane(desktop);

		this.setSize(640, 480);

		// Background
		ImageIcon imageBack = new ImageIcon("images/pyroqual_bg.png");
		JLabel background = new JLabel(imageBack);
		background.setBounds(0, 0, imageBack.getIconWidth(), imageBack
				.getIconHeight());
		getContentPane().add(background, new Integer(Integer.MIN_VALUE));

		mainMenu = new JMenuBar();

		fileMenu = new JMenu("File");
		fileMenu.setMnemonic(KeyEvent.VK_F);
		fileMenu.getAccessibleContext().setAccessibleDescription(
				"File menu, nice ehh?");

		loadMenuItem = new JMenuItem("Load");
		fileMenu.add(loadMenuItem);

		mainMenu.add(fileMenu);

		// Single sequence menu:

		singleSeqMenu = new JMenu("Single sequence");
		singleSeqMenu.setMnemonic(KeyEvent.VK_S);
		singleSeqMenu.getAccessibleContext().setAccessibleDescription(
				"List of loaded sequences");

		singleSeqMenu.add("No sequences loaded! Use File->Load");

		singleSeqSearchMI = new JMenuItem("Search...");
		singleSeqSearchMI.addActionListener(this);

		singleSeqPrevMI = new JMenuItem("Previous " + GENESINMENU);
		singleSeqPrevMI.setActionCommand("prevSeq");
		singleSeqPrevMI.addActionListener(this);

		singleSeqNextMI = new JMenuItem("Next " + GENESINMENU);
		singleSeqNextMI.setActionCommand("nextSeq");
		singleSeqNextMI.addActionListener(this);

		mainMenu.add(singleSeqMenu);

		// Multiple sequences menu:

		multipleSeqMenu = new JMenu("Multiple sequences");

		msLoadClusterMI = new JMenuItem("Load cluster file");
		msLoadClusterMI.setActionCommand("loadCluster");
		msLoadClusterMI.addActionListener(this);
		multipleSeqMenu.add(msLoadClusterMI);

		msRandomMI = new JMenuItem("Random sequences");
		msRandomMI.setActionCommand("multipleRandom");
		msRandomMI.addActionListener(this);

		mainMenu.add(multipleSeqMenu);

		// Help Menu:

		helpMenu = new JMenu("Help");
		helpMenuItem = new JMenuItem("Help");
		aboutMenuItem = new JMenuItem("About");

		helpMenu.add(helpMenuItem);
		helpMenu.add(aboutMenuItem);

		mainMenu.add(helpMenu);

		helpMenuItem.addActionListener(this);
		aboutMenuItem.addActionListener(this);

		this.setJMenuBar(mainMenu);

		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		loadMenuItem.addActionListener(this);

		this.setVisible(true);
	}

	public void actionPerformed(ActionEvent e) {
		if (e.getActionCommand().compareTo("Load") == 0) {
			try {
				loadGeneNames();
				// TODO: View successfull load dialog box.
			} catch (IOException e1) {
				// TODO: Write a dialog box!
				e1.printStackTrace();
			}
		} else if (e.getActionCommand().compareTo("Search...") == 0) {

			try {
				String sequenceToLoad = (String) JOptionPane.showInputDialog(
						new JFrame(""), "Enter the WHOLE name of the gene",
						"Search gene...", JOptionPane.PLAIN_MESSAGE, null,
						null, "");
				if (sequenceName.contains(sequenceToLoad)) {
					desktop.add(new SingleSequenceView(pyroDataIn
							.loadSequence(sequenceToLoad)));
				} else {
					JOptionPane.showMessageDialog(new JFrame("Not found"),
							sequenceToLoad + " not found.");
				}
			} catch (IOException e1) {
				// TODO: Show error dialog.
				e1.printStackTrace();
			}

		} else if (e.getActionCommand().compareTo("prevSeq") == 0) {
			seqCurrentFirst -= GENESINMENU;
			if (seqCurrentFirst < 0) { // Should never happen.
				seqCurrentFirst = 0;
			}
			populateSingleSequenceMenu();
		} else if (e.getActionCommand().compareTo("nextSeq") == 0) {
			seqCurrentFirst += GENESINMENU;
			populateSingleSequenceMenu();
		} else if (e.getActionCommand().compareTo("Help") == 0) {
			System.out.println("Help pressed!");
		} else if (e.getActionCommand().compareTo("About") == 0) {
			System.out.println("About pressed!");
		} else if (e.getActionCommand().compareTo("multipleRandom") == 0) {
			System.out.println("Random in multiple sequences pressed");
		} else if (e.getActionCommand().compareTo("loadCluster") == 0) {
			try {
				loadClusterFile();
			} catch (IOException e1) {
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}
		} else {
			try {
				desktop.add(new SingleSequenceView(pyroDataIn.loadSequence(e
						.getActionCommand())));
			} catch (IOException e1) {
				// TODO: Show error dialog.
				e1.printStackTrace();
			}

		}
	}

	private void loadClusterFile() throws IOException {
		JFileChooser clusterFC = new JFileChooser("Select cluster file");
		int returnVal = clusterFC.showDialog(this, "Load cluster file");
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			try {
				clusterMap = BlastClustReader.readAll(clusterFC
						.getSelectedFile());
				populateMultipleSequenceMenu();
			} catch (FileNotFoundException e) {
				JOptionPane.showMessageDialog(this, "Error, file not found. "
						+ e.getMessage());
			}
		}
		populateMultipleSequenceMenu();
	}

	private void loadGeneNames() throws IOException {
		JFileChooser sequenceFileChooser = new JFileChooser(
				"Select sequence file");
		int returnVal = sequenceFileChooser.showDialog(this, "Load sequence");
		if (returnVal == JFileChooser.APPROVE_OPTION) {
			JFileChooser qualityFileChooser = new JFileChooser(
					"Select corresponding quality file");
			qualityFileChooser.setCurrentDirectory(new File(sequenceFileChooser
					.getSelectedFile().getParent()));
			returnVal = qualityFileChooser
					.showDialog(this, "Load quality data");
			if (returnVal == JFileChooser.APPROVE_OPTION) {

				try {
					File seqFile = sequenceFileChooser.getSelectedFile();
					File qualityFile = qualityFileChooser.getSelectedFile();

					pyroDataIn = new FastaReader(seqFile, qualityFile);
					sequenceName = pyroDataIn.readAllNames();
					seqCurrentFirst = 0;
					populateSingleSequenceMenu();

				} catch (FileNotFoundException e) {
					JOptionPane.showMessageDialog(this,
							"Error, file not found. " + e.getMessage());
				}

			}
		}

	}

	private void populateMultipleSequenceMenu() {
		if (clusterMap != null) {
			multipleSeqMenu.removeAll();
			multipleSeqMenu.add(msRandomMI);
			int numberOfClusters = clusterMap.size();
			msClusterMI = new JMenuItem[numberOfClusters];

			Object[] clusterArray = clusterMap.keySet().toArray();
			for (int i = 0; i < numberOfClusters; i++) {
				msClusterMI[i] = new JMenuItem((String) clusterArray[i]);
				multipleSeqMenu.add(msClusterMI[i]);
			}
		}

	}

	private void populateSingleSequenceMenu() {
		if (sequenceName.size() > 0) {
			singleSeqMenu.removeAll();

			singleSeqMenu.add(singleSeqSearchMI);
			if (seqCurrentFirst != 0) {
				singleSeqMenu.add(singleSeqPrevMI);
			}
			singleSeqMenu.addSeparator();
			singleSeqMenu.add(new JMenuItem("Showing gene "
					+ (seqCurrentFirst + 1) + " to "
					+ (seqCurrentFirst + GENESINMENU) + " of "
					+ sequenceName.size()));
			singleSeqMenu.addSeparator();
			sequenceMenuItem = new JMenuItem[GENESINMENU];

			Iterator<String> seqNameIterator = sequenceName
					.descendingIterator();
			int skip = 0;
			while (skip < seqCurrentFirst && seqNameIterator.hasNext()) {
				seqNameIterator.next();
				skip++;
			}
			int i = 0;
			while (i < GENESINMENU && seqNameIterator.hasNext()) {
				sequenceMenuItem[i] = new JMenuItem(seqNameIterator.next());
				sequenceMenuItem[i].addActionListener(this);
				singleSeqMenu.add(sequenceMenuItem[i]);
				i++;
			}
			singleSeqMenu.addSeparator();
			if (seqNameIterator.hasNext()) {
				singleSeqMenu.add(singleSeqNextMI);
			}
		}
	}

}
